package com.hmall.order.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hmall.common.dto.Address;
import com.hmall.common.dto.Item;
import com.hmall.feign.client.AddressClient;
import com.hmall.feign.client.ItemClient;
import com.hmall.order.mapper.OrderDetailMapper;
import com.hmall.order.mapper.OrderLogisticsMapper;
import com.hmall.order.mapper.OrderMapper;
import com.hmall.order.pojo.Order;
import com.hmall.order.pojo.OrderDetail;
import com.hmall.order.pojo.OrderDto;
import com.hmall.order.pojo.OrderLogistics;
import com.hmall.order.service.IOrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.core.MessageDeliveryMode;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class OrderService extends ServiceImpl<OrderMapper, Order> implements IOrderService {
    @Autowired
    private OrderDetailMapper orderDetailMapper;
    @Autowired
    private ItemClient itemClient;
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private AddressClient addressClient;
    @Autowired
    private OrderLogisticsMapper orderLogisticsMapper;
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createOrderAndDetail(OrderDto orderDto) {
//        根据雪花算法生成订单id
//        商品微服务提供FeignClient，实现根据id查询商品的接口
//        根据itemId查询商品信息
        Item item = itemClient.getById(orderDto.getItemId());
//        基于商品价格、购买数量计算商品总价：totalFee
        Long totalFee=orderDto.getNum()*item.getPrice();
//        封装Order对象，初识status为未支付
        Order order = new Order();
        //order.setUserId(Long.valueOf(UserThreadLocal.getSubject()));
        order.setUserId(2L);
        order.setPaymentType(3);
        order.setStatus(1);
        order.setTotalFee(totalFee);
        order.setCreateTime(LocalDateTime.now());
//        将Order写入数据库tb_order表中
        orderMapper.insert(order);
//        将商品信息、orderId信息封装为OrderDetail对象，写入tb_order_detail表
        OrderDetail orderDetail = new OrderDetail();
        Long orderId = order.getId();
        BeanUtils.copyProperties(item,orderDetail);
        orderDetail.setOrderId(orderId);
        orderDetail.setNum(orderDto.getNum());
        orderDetail.setItemId(orderDto.getItemId());
        orderDetailMapper.insert(orderDetail);
//        将user-service的根据id查询地址接口封装为FeignClient
//        根据addressId查询user-service服务，获取地址信息
        Address address = addressClient.findAddressById(orderDto.getAddressId());
//        将地址封装为OrderLogistics对象，写入tb_order_logistics表
        OrderLogistics orderLogistics = new OrderLogistics();
        BeanUtils.copyProperties(address,orderLogistics);
        orderLogistics.setOrderId(orderId);
        orderLogistics.setCreateTime(LocalDateTime.now());
        orderLogisticsMapper.insert(orderLogistics);
//        在item-service提供减库存接口，并编写FeignClient
//        调用item-service的减库存接口
        itemClient.decreamStock(orderDto.getItemId(), orderDto.getNum());
        try {
            sendMessage(orderId);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        return orderId;
    }
    @Autowired
    private RabbitTemplate rabbitTemplate;
    public void sendMessage(Long orderId) throws InterruptedException {
        //设置生成CorrelationData对象，并设置唯一id
        CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
        /*rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
            @Override
            public void confirm(CorrelationData correlationData, boolean ack, String s) {
                if(ack){
                    log.info("消息发送到交换机成功，id为:{}",correlationData.getId());
                }else{
                    log.error("消息发送失败，id为:{},错误信息为:{}",correlationData.getId(),s);
                }
            }
        });*/
        Message msg = MessageBuilder.withBody(orderId.toString().getBytes(StandardCharsets.UTF_8))
                .setDeliveryMode(MessageDeliveryMode.PERSISTENT)
                .setHeader("x-delay","1800000")
                .build();
        rabbitTemplate.convertAndSend("delay.exchange", "delay.key", msg,correlationData);
        TimeUnit.SECONDS.sleep(1);
    }
}
